#include "DispatchHandler.h"
#include "JME_JsonFile.h"
#include "JME_RPCManager.h"
#include "AccountServer.h"

#include "RPC_dispatch.pb.h"
#include "account.pb.h"

#include <sstream>

const static int MAX_SQL_LENGTH = 256;

#ifdef WIN32
#define DBSPRINT sprintf_s
#else
#define DBSPRINT sprintf
#endif // WIN32

void DispatchHandler::init()
{
	regMessageHandler(client_request_login_MsgId_requestLogin, boost::bind(&DispatchHandler::requestLogin, _1, _2));
}

void DispatchHandler::requestLogin(int net, const google::protobuf::Message* params)
{
	auto proto = static_cast<const RPC_RequestHandle*>(params);

	int server_id = proto->server_id();

	server_login_response response;
	response.set_state(server_login_response_LoginState_Unknown);

	bool succeed = false;
	int account_id = 0;

	__TRY__
		do
		{
			client_request_login client_proto;
			client_proto.ParseFromString(proto->params());

			auto& name = client_proto.name();
			auto& pwd = client_proto.passwd();

			MysqlConnHelper mysqlconn(AccountServer::getInstance()->getMysqlDBPool());

			char sql[MAX_SQL_LENGTH];

			DBSPRINT( sql, "select accont_id, password from account_db where username='%s'", name.c_str());
			if (!mysqlconn->query(sql))
			{
				response.set_state(server_login_response_LoginState_Unknown);
			}
			else if( mysqlconn->isResEmpty() ) // No username found
			{
				response.set_state(server_login_response_LoginState_NotFound);
			}
			else
			{
				MYSQL_RES* res = mysqlconn->getRes();
				MYSQL_ROW row = mysql_fetch_row( res );

				if( !row )
					break;

				string pwd = row[1];
				if ( pwd.compare(pwd) )
				{
					response.set_state(server_login_response_LoginState_PasswdError);
				}
				else
				{
					account_id = boost::lexical_cast<int>(row[0]);
					response.set_state(server_login_response_LoginState_Succeed);
					response.set_account_id(account_id);

					succeed = true;
				}
			}
			if (succeed)
			{
				MongodbConnHelper mongoconn(AccountServer::getInstance()->getMongoDBPool());

				static string dbname = boost::str(boost::format("server_%d.account_auth") % AccountServer::getInstance()->_serverId);

				auto createAuthKey = [](const string& name, int net)
				{
					static int volatile idx = 0;
					stringstream sst;
					sst << name << "_" << net << "_" << boost::this_thread::get_id() << "_" << ++idx;
					return sst.str();
				};

				auto autoKey = createAuthKey(name, net);
				response.set_auth_key(autoKey);

				mongoconn->updateBsonVal(dbname, BSON("account_id"<<account_id<<"server_id"<<server_id), BSON("account_id"<<account_id<<"server_id"<<server_id<<"auth_key"<<autoKey));
			}
		}while(0);
		
	__CATCH_CHAR_ERROR__

		LOGE("Get db connector failed, error ==> [ %s ]", e);

	__CATCH_STD_EXCEPT_ERROR__

		LOGE("Parse protobuf error ==> [ %s ]", e.what());

	__TRY_END__

	{
		RPC_SendClient p;
		p.set_msg_id(server_login_response_MsgId_loginResponse);
		p.set_net_id(net);
		p.set_params(response.SerializeAsString());

		GETRPC(proto->gate().c_str())->callRpcMethod("sendClient", &p);
	}
}

